package ca.cbc.medialib.service;

import ca.cbc.medialib.Bootstrap;
import ca.cbc.medialib.entity.Category;
import ca.cbc.medialib.entity.Media;
import ca.cbc.medialib.exception.ThePlatformObjectNotFoundException;

import com.google.common.base.Function;
import com.google.common.base.Strings;
import com.google.common.collect.Collections2;
import com.theplatform.data.api.DataObjectField;
import com.theplatform.data.api.client.query.ByTitle;
import com.theplatform.data.api.client.query.Query;
import com.theplatform.data.api.client.query.ValueQuery;
import com.theplatform.data.api.exception.ObjectNotFoundException;
import com.theplatform.data.api.objects.Feed;
import com.theplatform.media.api.client.query.media.ByCategoryIds;
import com.theplatform.media.api.data.objects.ContentType;
import com.theplatform.media.api.data.objects.MediaFile;
import com.theplatform.media.api.fields.MediaField;
import org.slf4j.Logger;

import java.net.URI;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * PLEASE USE MediaService Class
 */
@Deprecated
public final class GetMedia {

    private static Logger logger = org.slf4j.LoggerFactory.getLogger(GetMedia.class);

    public enum MediaFields {
        ID(DataObjectField.id.toString()),
        TITLE(DataObjectField.title.toString()),
        DESCRIPTION(DataObjectField.description.toString()),
        CATEGORIES(MediaField.categories.toString()),
        KEYWORDS(MediaField.keywords.toString()),
        CONTENT(MediaField.content.toString()),
        CUSTOM(DataObjectField.customValues.toString()),
        AVAILABLE_DATE(MediaField.availableDate.toString()),
        ALL(MediaField._all.toString());
        private String fieldName;

        public String getThePlatformField() {
            return fieldName;
        }

        private MediaFields(String s) {
            fieldName = s;
        }
    }

    private List<MediaFields> fields = new ArrayList<MediaFields>();
    private List<Query> query;

    private GetMedia() {
    }

    public static GetMedia getInstance() {
        return new GetMedia();
    }


    public GetMedia fetchTitle() {
        fields.add(MediaFields.TITLE);
        return this;
    }

    public GetMedia fetchDescription() {
        fields.add(MediaFields.DESCRIPTION);
        return this;
    }

    public GetMedia fetchCategories() {
        fields.add(MediaFields.CATEGORIES);
        return this;
    }

    public GetMedia fetchCustom() {
        fields.add(MediaFields.CUSTOM);
        return this;
    }

    public GetMedia fetchContent() {
        fields.add(MediaFields.CONTENT);
        return this;
    }

    public GetMedia fetchAll() {
        fields.add(MediaFields.ALL);
        return this;
    }

    public GetMedia like(Media sample) throws ThePlatformObjectNotFoundException {
        createQuery(sample);
        return this;
    }

    public Media getMedia(String id) throws URISyntaxException, ThePlatformObjectNotFoundException {
        try {
            com.theplatform.media.api.data.objects.Media m = Bootstrap.instance.getMediaClient()
                    .get(new URI(id), createProjectionFields());

            if (m == null) {
                logger.warn("Could not find the media with id {}", id);
                return null;
            }
            return mediaConverter.apply(m);
        } catch (URISyntaxException e) {
            throw e;
        } catch (ObjectNotFoundException e) {
            throw new ThePlatformObjectNotFoundException("Media object not found", e);
        }

    }

    protected Feed<com.theplatform.media.api.data.objects.Media> getFeed() {
        Feed<com.theplatform.media.api.data.objects.Media> mediaFeed = Bootstrap.instance.getMediaClient().getAll(
                createProjectionFields(),
                query == null ? null : query.toArray(new Query[0]),
                null,
                null,
                true);
        return mediaFeed;
    }

    public Collection<Media> run() {

        Feed<com.theplatform.media.api.data.objects.Media> mediaFeed = Bootstrap.instance.getMediaClient().getAll(
                createProjectionFields(),
                query.toArray(new Query[0]),
                null,
                null,
                true);

        return Collections2.transform(mediaFeed.getEntries(), mediaConverter);
    }

    private String[] createProjectionFields() {
        List<String> fs = new ArrayList<String>();
        for (MediaFields f : fields) {
            fs.add(f.getThePlatformField());
        }
        //_ALL is not working, I need to add all the fields manually
        if (fields.contains(MediaFields.ALL)) {
            for (MediaFields f : MediaFields.values()) {
                fs.add(f.getThePlatformField());
            }
        }
        fs.add(MediaFields.ID.toString());
        fs.add(MediaFields.CONTENT.toString());
        String[] a = fs.toArray(new String[0]);
        logger.debug("Projection fields are {}", Arrays.toString(a));
        return a;
    }

    private void createQuery(Media sample) throws ThePlatformObjectNotFoundException {
        //create query for categories

        Category category = null;
        if (sample.getCategories() != null && !sample.getCategories().isEmpty()) {

            Iterator<Category> itr = sample.getCategories().iterator();
            category = new CategoryService().findByFullTitle(itr.next().getFullTitle());
            if (itr.hasNext()) {
                logger.error("The sampleMedia for Query has more than one element, only the first one will be considered");
            }
        }
        query = new ArrayList<Query>();
        if (!Strings.isNullOrEmpty(sample.getTitle())) {
            query.add(new ByTitle(sample.getTitle()));
        }
        if (!Strings.isNullOrEmpty(sample.getKeywords())) {
            query.add(new ValueQuery<String>("keywords", sample.getKeywords()));
        }
        if (!Strings.isNullOrEmpty(sample.getGenre())) {
            query.add(new ValueQuery<String>("genre", sample.getGenre()));
        }
        if (category != null) {
            try {
                query.add(new ByCategoryIds(new URI(String.valueOf((category.getId())))));
            } catch (URISyntaxException e) {
                logger.error("Could not create URI from " + category.getId());
                throw new RuntimeException("Could not create URI from " + category.getId(), e);
            }
        }


    }

    private String nullOrString(Object o) {
        return o == null ? null : o.toString();
    }

    private Date nullOrDate(Object o) {
        try {
            return o == null ? null : parseDate(o.toString());
        } catch (ParseException e) {
            logger.warn("Could not parse the date object {}", o.toString());
            return null;
        }
    }

    private Date parseDate(String s) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("M/d/y h:m a");
        return sdf.parse(s);
    }

    protected Function<com.theplatform.media.api.data.objects.Media, Media> mediaConverter = new Function<com.theplatform.media.api.data.objects.Media, Media>() {
        @Override
        public Media apply(com.theplatform.media.api.data.objects.Media media) {
            MediaFile movieFile = null;
            if (media.getContent() != null) {
                for (MediaFile f : media.getContent()) {
                    if (f.getContentType() == ContentType.video) {
                        logger.debug("media file is {}", f.getDownloadUrl());
                        movieFile = f;
                    }
                }
            }

            Media.Builder builder = Media.Builder.getBuilder();
            // builder.withId(nullOrString(media.getId().toString()));
            builder.withTitle(nullOrString(media.getTitle()));
            builder.withDescription(nullOrString(media.getDescription()));
//            builder.withAirDate(nullOrDate(media.));
//            builder.withApproved(media.getApproved());
            builder.withAdCategory(nullOrString(media.getCustomValue(Bootstrap.instance.getNameSpace(), "adCategory")));
            builder.withGenre(nullOrString(media.getCustomValue(Bootstrap.instance.getNameSpace(), "genre")));
            builder.withKeywords(nullOrString(media.getCustomValue(Bootstrap.instance.getNameSpace(), "keywords")));
            builder.withAvailableDate(nullOrDate(media.getAvailableDate()));
            builder.withEpisodeNumber(nullOrString(media.getCustomValue(Bootstrap.instance.getNameSpace(), "episodeNumber")));
            builder.withSeasonNumber(nullOrString(media.getCustomValue(Bootstrap.instance.getNameSpace(), "seasonNumber")));
            //           builder.withCategories(media.getCategories() == null ? null : Collections2.transform(Arrays.asList(media.getCategories()), CategoryService.categoryFunction));
//            builder.withThumbnailUrl(media.get);
            // builder.withMobileId((String) (movieFile != null && movieFile.getReleases()!= null && movieFile.getReleases().length!=0 ? movieFile.getReleases()[0].getCustomValue(Bootstrap.instance.getNameSpace(),"yospaceID") : ""));
            builder.withAvailableDate(media.getAvailableDate());
            String duration = movieFile == null ? "" : movieFile.getDuration().getHour() + ":" + movieFile.getDuration().getMinute() + ":" + movieFile.getDuration().getSecond();
/*            if(media.getCategories() != null && media.getCategories().length >0){
                for ( CategoryInfo cat : media.getCategories()){
                    Category c = new Category(null,null,"/"+cat.getName(),null,null,null,null,null);
                    categories.add(c);
                }
            }
             builder.withCategories(categories);*/
            builder.withLength(duration);
            return builder.buildNew();
        }
    };


}
